(ns picture_gallery.routes.auth
  (:require [noir.response :as response]
            [noir.session :as session]
            [compojure.core :refer :all]
            [hiccup.form :refer :all]
            [picture-gallery.routes.home :refer :all]
            [picture-gallery.views.layout :as layout]
            [picture_gallery.util :refer [gallery-path]]
            [noir.validation :as vali]
            [picture_gallery.models.db :as db]
            [noir.util.crypt :as crypt]
            [noir.util.anti-forgery :refer :all]
            )
  (:import (org.postgresql.util PSQLException)
           java.io.File))

(defn valid? [id pass pass1]
  (vali/rule (vali/has-value? id)
             [:id "填用户名啊大佬"])
  (vali/rule (vali/min-length? pass 6)
             [:pass "密码至少6位啊大佬"])
  (vali/rule (= pass pass1)
             [:pass "你输入两次密码不一样啊大佬"])
  (not (vali/errors? :id :pass))
  )

(defn error-item [[error]]
  [:div.error error])

(defn control [id label field]
  (list
    (vali/on-error id error-item)
    label
    field
    [:br]))

(defn registration-page [& [id]]
  (layout/base
    (form-to [:post "/register"]
      ;(label "user-id" "user id")
      ;(text-field "id" id)
      ;[:br]
      ;(label "pass" "password")
      ;(password-field "pass")
      ;[:br]
      ;(label "pass1" "retype password")
      ;(password-field "pass1")
      ;[:br]
             (anti-forgery-field)
      (control :id
               (label "user-id" "user id")
               (text-field {:tabindex 1} "id" id))
      (control :pass
               (label "pass" "password")
               (password-field {:tabindex 2} "pass"))
      (control :pass1
               (label "pass1" "retype password")
               (password-field {:tabindex 3} "pass1"))
      (submit-button {:tabindex 4} "create accout"))))

(defn format-error [id ex]
  (cond
    (and (instance? PSQLException ex)
         (= 0 (.getErrorCode ex)))
    (str "The user with id " id " already exists!")

    :else
    "An error has occured while processing the request")
  )

(defn create-gallery-path []                                ;创建新相册
  (let [user-path (File. (gallery-path))]
    (if-not (.exists user-path) (.mkdir user-path))         ;新建目录
    (str (.getAbsolutePath user-path) File/separator))      ;返回路径
  )

(defn handle-registration [id pass pass1]
  (if (valid? id pass pass1)
    (try
      (db/create-user {:id id :pass (crypt/encrypt pass)})
      (session/put! :user id)
      (create-gallery-path)
      (response/redirect "/")
      (catch Exception ex
         (println ex)
        (vali/rule false [:id (format-error id ex)])
        (registration-page)))
    (registration-page id))
  )

(defn handle-login [id pass]
  (let [user (db/get-user id)]
    (if (and user (crypt/compare pass (:pass user)))
      (session/put! :user id)
      (vali/rule false [:login "密码错误"]))
      )
  ;(response/redirect "/")
  (home)
  )

(defn login-page [& [id] ]
  (layout/base
    (form-to [:post "/login"]
             (anti-forgery-field)
             "Create a hidden field with the session anti-forgery token as its value.
  This ensures that the form it's inside won't be stopped by the anti-forgery
  middleware."
             (control :id
                      (label "user-id" "user id")
                      (text-field "id" id))
             (control :pass
                      (label "pass" "password")
                      (password-field "pass"))
             (submit-button "login"))
    ))

(defroutes auth-routes
           (GET "/register" []
             (registration-page))
           (POST "/register" [id pass pass1]
             (handle-registration id pass pass1))
           (GET "/login" []
             (login-page))
           (POST "/login" [id pass]
             (handle-login id pass))
           (GET "/logout" []
             (session/clear!)
             (response/redirect "/")))
